package com.yanqu.road.server.manager.douluodalu;

import com.alibaba.fastjson.JSONObject;
import com.yanqu.road.entity.activity.ActivityConfig;
import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.douluodalu.DouLuoDaLuAttackInfo;
import com.yanqu.road.entity.activity.douluodalu.DouLuoDaLuTeamLeaveTip;
import com.yanqu.road.entity.activity.douluodalu.DouLuoDaLuUserPatrons;
import com.yanqu.road.entity.activity.douluodalu.config.DouLuoDaLuConfig;
import com.yanqu.road.entity.activity.douluodalu.config.DouLuoDaLuEventInfo;
import com.yanqu.road.entity.activity.douluodalu.config.DouLuoDaLuRegionInfo;
import com.yanqu.road.entity.activity.douluodalu.data.*;
import com.yanqu.road.entity.activity.douluodalu.enums.eDouLuoDaLuEventType;
import com.yanqu.road.entity.activity.douluodalu.log.DouLuoDaLuBattleNoticeData;
import com.yanqu.road.entity.activity.douluodalu.log.DouLuoDaLuEventNoticeData;
import com.yanqu.road.entity.activity.douluodalu.log.DouLuoDaLuTryTrainRecordData;
import com.yanqu.road.entity.activity.douluodalu.result.DouLuoDaLuCalBloodBaseInfo;
import com.yanqu.road.entity.enums.eChatContentType;
import com.yanqu.road.entity.enums.eGamePlayerEventType;
import com.yanqu.road.entity.log.cross.LogDouLuoDaLuNpcBloodData;
import com.yanqu.road.entity.log.cross.LogDouLuoDaLuTeam;
import com.yanqu.road.entity.log.cross.LogDouLuoDaLuUserHunLi;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.entity.rank.cross.TeamBaseInfo;
import com.yanqu.road.logic.bussiness.activity.DouLuoDaLuActivityBusiness;
import com.yanqu.road.logic.bussiness.servercenter.ActivityBussiness;
import com.yanqu.road.logic.pb.DouLuoDaLuPb;
import com.yanqu.road.logic.pb.PlayerBasePb;
import com.yanqu.road.server.manager.log.CrossAutoLogMgr;
import com.yanqu.road.server.manger.CrossUnionServerGroupMgr;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.pb.activity.douluodalu.DouLuoDaLuProto;
import com.yanqu.road.pb.player.PlayerProto;
import com.yanqu.road.pb.worldmessage.WorldMessageProto;
import com.yanqu.road.server.logic.MessageHelper;
import com.yanqu.road.server.manager.activity.ActivityMgr;
import com.yanqu.road.server.manager.activity.ActivityTeamRankMgr;
import com.yanqu.road.message.YanQuMessage;
import com.yanqu.road.server.protocol.ClientProtocol;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 猎魂森林
 */
public class CrossDouLouDaLuActivity {

    static int PAGE_SIZE = 10;

    int activityId;
    int groupId;

    DouLuoDaLuConfig config;

    Random random = new Random();

    /**
     * 活动信息
     */
    ActivityInfo activityInfo;

    /**
     * 各NPC事件的动态血量
     */
    Map<Integer, DouLuoDaLuNpcBloodData> npcBlood = new ConcurrentHashMap<>();

    /**
     * 队伍最大id
     */
    public AtomicInteger maxTeamId;

    /**
     * 协助记录最大id
     */
    public AtomicLong maxHelpRecordId;

    /**
     * 试炼宝库隐藏
     */
    private DouLuoDaLuBox box;

    /**
     * 所有玩家基本数据+森林数据，key:玩家ID
     */
    Map<Long, DouLuoDaLuUserData> allUserMap = new ConcurrentHashMap<>();

    /**
     * 按区域存放玩家数据，key:区域ID
     */
    Map<Integer, Map<Long, DouLuoDaLuUserData>> areaUserMap = new ConcurrentHashMap<>();

    /**
     * 玩家求助记录(包括 击杀和未击杀)
     */
    Map<Long, List<DouLuoDaLuHelpRecordData>> helpRecordDataMap = new ConcurrentHashMap<>();

    /**
     * 所有队伍数据，key:队伍ID
     */
    Map<Integer, DouLuoDaLuTeamData> allTeamMap = new ConcurrentHashMap<>();

    /**
     * 按区服存放队伍数据，key:区服ID
     */
    Map<Long, List<DouLuoDaLuTeamData>> serverTeamMap = new ConcurrentHashMap<>();

    /**
     * 需要删除的队伍 （临时存放，入库后移除）
     */
    List<DouLuoDaLuTeamData> deleteList = new ArrayList<>();

    /**
     * 队伍聊天数据，key:队伍ID
     */
    Map<Integer, WorldMessageProto.WorldMessageListMsg.Builder> teamChatMap = new ConcurrentHashMap<>();

    /**
     * 所有玩家魂决战斗数据，key:玩家ID
     */
    Map<Long, DouLuoDaLuPatronsBattleData> battleDataMap = new ConcurrentHashMap<>();

    //宝库日志
    private List<DouLuoDaLuTryTrainRecordData> recordList = new ArrayList<>();

    //森林事件日志
    private List<DouLuoDaLuEventNoticeData> eventNoticeDataList = new ArrayList<>();

    //对决公告
    private List<DouLuoDaLuBattleNoticeData> battleNoticeDataList = new ArrayList<>();

    public CrossDouLouDaLuActivity(int activityId, int groupId) {
        this.activityId = activityId;
        this.groupId = groupId;
        init();
    }


    public boolean init() {
        ActivityInfo activityInfo = ActivityMgr.getActivityInfo(activityId);
        //配置初始化
        initConfig(activityInfo);
        //数据初始化
        initData(activityInfo);
        return true;
    }

    public boolean initConfig(ActivityInfo activityInfo){
        List<Integer> activityIdList = new ArrayList<>();
        activityIdList.add(activityInfo.getActivityId());
        Map<String, ActivityConfig> activityConfigMap = ActivityBussiness.getActivityConfigMap(activityIdList).get(activityInfo.getActivityId());

        //配置项
        DouLuoDaLuConfig tempConfig = new DouLuoDaLuConfig();
        DouLuoDaLuConfig.parseConfig(tempConfig, activityConfigMap, activityInfo);
        tempConfig.setRegionInfoList(DouLuoDaLuActivityBusiness.getDouLuoDaLuRegionInfoList(activityInfo.getActivityId()));
        tempConfig.setEventInfoList(DouLuoDaLuActivityBusiness.getDouLuoDaLuEventInfoList(activityInfo.getActivityId()));
        DouLuoDaLuConfig.parseBoxOpenConsume(tempConfig);

        for (DouLuoDaLuEventInfo eventInfo : tempConfig.getEventInfoList()) {
            if(eventInfo.getEventType() == eDouLuoDaLuEventType.PlayerEvent.getIntValue()){
                tempConfig.getPlayerEventId().add(eventInfo.getEventId());
            }
            if(eventInfo.getEventType() == eDouLuoDaLuEventType.ShrekGiftsEvent.getIntValue()){
                tempConfig.getSevenEventId().add(eventInfo.getEventId());
            }
        }

        config = tempConfig;
        this.activityInfo = activityInfo;
        return true;
    }

    public boolean initData(ActivityInfo activityInfo){
        Map<Integer, Map<Long, DouLuoDaLuUserData>> areaUserMapTemp = new ConcurrentHashMap<>();
        for (DouLuoDaLuRegionInfo regionInfo : config.getRegionInfoList()) {
            areaUserMapTemp.put(regionInfo.getRegionId(), new ConcurrentHashMap<>());
        }
        maxTeamId = new AtomicInteger(DouLuoDaLuActivityBusiness.getMaxTeamId(activityInfo.getActivityId(), groupId));
        maxHelpRecordId = new AtomicLong(DouLuoDaLuActivityBusiness.getMaxHelpRecordId(activityInfo.getActivityId(), groupId));

        //玩家
        Map<Long, DouLuoDaLuUserData> allUserMapTemp = DouLuoDaLuActivityBusiness.getAllDouLuoDaLuUserData(activityInfo.getActivityId(), groupId);

        //协助记录
        Map<Long, List<DouLuoDaLuHelpRecordData>> helpRecordDataMapTemp = new ConcurrentHashMap<>();
        List<DouLuoDaLuHelpRecordData> helpRecordDataList = DouLuoDaLuActivityBusiness.getDouLuoDaLuHelpRecordData(activityInfo.getActivityId(), groupId);
        for (DouLuoDaLuHelpRecordData helpRecordData : helpRecordDataList) {
            helpRecordDataMapTemp.putIfAbsent(helpRecordData.getUserId(), new ArrayList<>());
            helpRecordDataMapTemp.get(helpRecordData.getUserId()).add(helpRecordData);
            if(helpRecordData.getKilledUserId() == 0){
                DouLuoDaLuUserData userData = allUserMapTemp.get(helpRecordData.getUserId());
                if(userData != null && userData.getCurrentHelpRecordData() == null){
                    userData.setCurrentHelpRecordData(helpRecordData);
                    if(helpRecordData.getTargetId() > 1000000){
                        DouLuoDaLuUserData enemy = allUserMapTemp.get(helpRecordData.getTargetId());
                        if(enemy != null) {
                            userData.getCanAttackUserSet().add(enemy);
                        }
                    }
                }else {
                    CrossDouLuoDaLuMgr.getLogger().error("current help data for user {} is more", helpRecordData.getUserId());
                }
            }
        }

        //战斗数据
        Map<Long, DouLuoDaLuPatronsBattleData> battleDataMapTemp = DouLuoDaLuActivityBusiness.getDouLuoDaLuPatronsBattleData(activityInfo.getActivityId(), groupId);


        for (Map.Entry<Long, DouLuoDaLuUserData> userDataEntry : allUserMapTemp.entrySet()) {
            DouLuoDaLuUserData userData = userDataEntry.getValue();
            areaUserMapTemp.get(userData.getRegionId()).put(userData.getUserId(), userData);
            DouLuoDaLuPatronsBattleData battleData = battleDataMapTemp.get(userData.getUserId());
            userData.setBattleData(battleData);

            if(userData.getEvent().getEventType() == eDouLuoDaLuEventType.PlayerEvent.getIntValue()){
                DouLuoDaLuUserData enemy = allUserMapTemp.get(userData.getEvent().getEnemyUserId());
                if(enemy != null){
                    userData.getCanAttackUserSet().add(enemy);
                }else {
                    CrossDouLuoDaLuMgr.getLogger().error("user {}'s event enemy user {} is null", userData.getUserId(), userData.getEvent().getEnemyUserId());
                }
            }
        }

        //队伍
        Map<Integer, DouLuoDaLuTeamData> teamDataMapTemp = DouLuoDaLuActivityBusiness.getDouLuoDaLuTeamData(activityInfo.getActivityId(), groupId);
        Map<Long, List<DouLuoDaLuTeamData>> serverTeamMapTemp = new ConcurrentHashMap<>();
        for (long serverId : activityInfo.getServerIdList()) {
            serverTeamMapTemp.put(serverId, new ArrayList<>());
        }
        for (Map.Entry<Integer, DouLuoDaLuTeamData> teamDataEntry : teamDataMapTemp.entrySet()) {
            DouLuoDaLuTeamData teamData = teamDataEntry.getValue();
            serverTeamMapTemp.get(teamData.getCaptainServerId()).add(teamData);
            updateTeamTotalEarn(teamData);
        }


        allUserMap = allUserMapTemp;
        areaUserMap = areaUserMapTemp;
        allTeamMap = teamDataMapTemp;
        serverTeamMap = serverTeamMapTemp;
        battleDataMap = battleDataMapTemp;
        teamChatMap = new ConcurrentHashMap<>();
        helpRecordDataMap = helpRecordDataMapTemp;

        box = DouLuoDaLuActivityBusiness.getDrawBoxData(activityInfo.getActivityId(), groupId);
        if(box == null){
            DouLuoDaLuBox tmpBox = new DouLuoDaLuBox(activityId, groupId);
            tmpBox.setCount(0);
            box = tmpBox;
        }
        npcBlood = DouLuoDaLuActivityBusiness.getDouLuoDaLuNpcBloodData(activityInfo.getActivityId(), groupId);

        //日志
        long todayTime = DateHelper.getTodayZeroTimeStamp();
        battleNoticeDataList = DouLuoDaLuActivityBusiness.getDouLuoDaLuBattleNoticeData(activityInfo.getActivityId(), todayTime, groupId);
        battleNoticeDataList.sort(new Comparator<DouLuoDaLuBattleNoticeData>() {
            @Override
            public int compare(DouLuoDaLuBattleNoticeData o1, DouLuoDaLuBattleNoticeData o2) {
                long g = o1.getLogTime() - o2.getLogTime();
                if(g > 0){
                    return 1;
                }
                if(g < 0){
                    return -1;
                }
                return 0;
            }
        });
        recordList = DouLuoDaLuActivityBusiness.getDouLuoDaLuTryTrainRecordData(activityInfo.getActivityId(), todayTime, groupId);
        recordList.sort(new Comparator<DouLuoDaLuTryTrainRecordData>() {
            @Override
            public int compare(DouLuoDaLuTryTrainRecordData o1, DouLuoDaLuTryTrainRecordData o2) {
                long g = o1.getTime() - o2.getTime();
                if(g > 0){
                    return 1;
                }
                if(g < 0){
                    return -1;
                }
                return 0;
            }
        });
        eventNoticeDataList = DouLuoDaLuActivityBusiness.getDouLuoDaLuEventNoticeData(activityInfo.getActivityId(), todayTime, groupId);
        eventNoticeDataList.sort(new Comparator<DouLuoDaLuEventNoticeData>() {
            @Override
            public int compare(DouLuoDaLuEventNoticeData o1, DouLuoDaLuEventNoticeData o2) {
                long g = o1.getLogTime() - o2.getLogTime();
                if(g > 0){
                    return 1;
                }
                if(g < 0){
                    return -1;
                }
                return 0;
            }
        });
        return true;
    }

    /**
     * 获取玩家基础数据
     */
    public DouLuoDaLuUserData getUser(long playerId, UserBaseInfo userBaseInfo, long allPatronsEarn, List<DouLuoDaLuUserPatrons> userPatrons) {
        DouLuoDaLuUserData userData = allUserMap.get(playerId);
        if(null == userData){
            synchronized (allUserMap) {
                userData = allUserMap.get(playerId);
                if(null == userData) {
                    // 初始化玩家
                    userData = new DouLuoDaLuUserData(activityId, groupId, playerId);
                    userData.setServerId(userBaseInfo.getServerId());
                    userData.setTotalBlood(allPatronsEarn);
                    userData.setBlood(allPatronsEarn);
                    //初始第一个区域
                    if (config.getRegionInfoList().size() > 0) {
                        int regionId = config.getRegionInfoList().get(0).getRegionId();
                        userData.setRegionId(regionId);
                        userData.addOpenRegionId(regionId);
                    }
                    userData.setEnergy(config.ENERGY_MAX);
                    userData.setEnergyLastTime(System.currentTimeMillis() / 1000);
                    allUserMap.put(playerId, userData);
                    addAreaUser(userData.getRegionId(), userData);
                }
            }
        }

        synchronized (userData) {
            updateUserData(userBaseInfo, allPatronsEarn, userPatrons, userData);
        }

        if(userPatrons.size() > 0){
            DouLuoDaLuPatronsBattleData battleData = battleDataMap.get(playerId);
            if(battleData == null){
                synchronized (battleDataMap) {
                    battleData = battleDataMap.get(playerId);
                    if(battleData == null) {
                        battleData = new DouLuoDaLuPatronsBattleData(activityId, groupId, userData.getUserId());
                        battleData.setScore(config.FIGHT_PLAYER_SCORE_BEGIN);
                        battleData.setServerId(userData.getServerId());
                        userData.setBattleData(battleData);
                        battleDataMap.put(playerId, battleData);
                    }
                }
            }
        }
        return userData;
    }

    /**
     * 区服同步玩家\门客信息
     */
    public void updateUserData(UserBaseInfo userBaseInfo, long allPatronsEarn, List<DouLuoDaLuUserPatrons> userPatrons, DouLuoDaLuUserData userData) {
        try {
            // 计算魂力
            boolean update = calHunLi(userData, userPatrons);
            userData.setUserBaseInfo(userBaseInfo);
            if (update) {
                userData.setAllPatronsEarn(allPatronsEarn);
                userData.setLastUpdateTime(System.currentTimeMillis());
                if(isCreateTeamPeriod() && userData.getTeamId() > 0){
                    updateTeamTotalEarn(userData.getTeamId());
                }
            }

            // 组队期间，更新血量
            if (isCreateTeamPeriod()) {
                userData.setTotalBlood(userData.getHunLi());
                userData.setBlood(userData.getTotalBlood());
            }
        }catch (Exception e){
            CrossDouLuoDaLuMgr.getLogger().error("user:{}", userData.getUserId(), e.getCause());
        }
    }

    private void updateTeamTotalEarn(int teamId) {
        DouLuoDaLuTeamData teamData = allTeamMap.get(teamId);
        if(teamData != null){
            updateTeamTotalEarn(teamData);
        }
    }

    public void updateTeamTotalEarn(DouLuoDaLuTeamData teamData) {
        try{
            long totalEarn = 0;
            for (Map.Entry<Long, Long> entry : teamData.getMemberList().entrySet()) {
                DouLuoDaLuUserData userData = allUserMap.get(entry.getKey());
                if(userData != null){
                    totalEarn += userData.getAllPatronsEarn();
                }
            }
            teamData.setTotalEarn(totalEarn);
        }catch (Exception e){

        }
    }

    /**
     * 数据保存
     */
    public void save() {
        //玩家
        for (Map.Entry<Long, DouLuoDaLuUserData> userDataEntry : allUserMap.entrySet()) {
            DouLuoDaLuUserData userData = userDataEntry.getValue();
            if(userData.isInsertOption()){
                DouLuoDaLuActivityBusiness.addDouLuoDaLuUserData(userData);
            }else if(userData.isUpdateOption()){
                DouLuoDaLuActivityBusiness.updateDouLuoDaLuUserData(userData);
            }
        }

        //队伍
        for (Map.Entry<Integer, DouLuoDaLuTeamData> teamDataEntry : allTeamMap.entrySet()) {
            DouLuoDaLuTeamData teamData = teamDataEntry.getValue();
            if(teamData.isInsertOption()){
                DouLuoDaLuActivityBusiness.addDouLuoDaLuTeamData(teamData);
            }else if(teamData.isUpdateOption()){
                DouLuoDaLuActivityBusiness.updateDouLuoDaLuTeamData(teamData);
            }
        }
        // 删除的队伍
        List<DouLuoDaLuTeamData> tempTeamList;
        synchronized (deleteList){
            tempTeamList = new ArrayList<>(deleteList);
            deleteList.clear();
        }
        for(DouLuoDaLuTeamData teamData : tempTeamList){
            if (teamData.isUpdateOption()) {
                DouLuoDaLuActivityBusiness.updateDouLuoDaLuTeamData(teamData);
            }
        }

        //协助
        for (Map.Entry<Long, List<DouLuoDaLuHelpRecordData>> listEntry : helpRecordDataMap.entrySet()) {
            List<DouLuoDaLuHelpRecordData> list = listEntry.getValue();
            for (int i = 0; i < list.size(); i++) {
                DouLuoDaLuHelpRecordData recordData = list.get(i);
                if(recordData.isInsertOption()){
                    DouLuoDaLuActivityBusiness.addDouLuoDaLuHelpRecordData(recordData);
                }else if(recordData.isUpdateOption()){
                    DouLuoDaLuActivityBusiness.updateDouLuoDaLuHelpRecordData(recordData);
                }
            }
        }

        for (Map.Entry<Long, DouLuoDaLuPatronsBattleData> battleDataEntry : battleDataMap.entrySet()) {
            DouLuoDaLuPatronsBattleData battleData = battleDataEntry.getValue();
            if(battleData.isInsertOption()){
                DouLuoDaLuActivityBusiness.addDouLuoDaLuPatronsBattleData(battleData);
            }else if(battleData.isUpdateOption()){
                DouLuoDaLuActivityBusiness.updateDouLuoDaLuPatronsBattleData(battleData);
            }
        }

        List<DouLuoDaLuTryTrainRecordData> recordListTemp = recordList;
        for (int i = 0; i < recordListTemp.size(); i++) {
            DouLuoDaLuTryTrainRecordData recordData = recordListTemp.get(i);
            if(recordData.isInsertOption()){
                DouLuoDaLuActivityBusiness.addDouLuoDaLuTryTrainRecordData(recordData);
            }
        }

        List<DouLuoDaLuBattleNoticeData> battleNoticeDataListTemp = battleNoticeDataList;
        for (int i = 0; i < battleNoticeDataListTemp.size(); i++) {
            DouLuoDaLuBattleNoticeData noticeData = battleNoticeDataListTemp.get(i);
            if(noticeData.isInsertOption()){
                DouLuoDaLuActivityBusiness.addDouLuoDaLuBattleNoticeData(noticeData);
            }
        }

        List<DouLuoDaLuEventNoticeData> eventNoticeDataListTemp = eventNoticeDataList;
        for (int i = 0; i < eventNoticeDataListTemp.size(); i++) {
            DouLuoDaLuEventNoticeData noticeData = eventNoticeDataListTemp.get(i);
            if(noticeData.isInsertOption()){
                DouLuoDaLuActivityBusiness.addDouLuoDaLuEventNoticeData(noticeData);
            }
        }

        for (Map.Entry<Integer, DouLuoDaLuNpcBloodData> dataEntry : npcBlood.entrySet()) {
            DouLuoDaLuNpcBloodData bloodData = dataEntry.getValue();
            if(bloodData.isInsertOption()){
                DouLuoDaLuActivityBusiness.addDouLuoDaLuNpcBloodData(bloodData);
            }else if(bloodData.isUpdateOption()){
                DouLuoDaLuActivityBusiness.updateDouLuoDaLuNpcBloodData(bloodData);
            }
        }

        if (box.isInsertOption()) {
            DouLuoDaLuActivityBusiness.addDouLuoDaLuBox(box);
        } else if (box.isUpdateOption()) {
            DouLuoDaLuActivityBusiness.updateDouLuoDaLuBox(box);
        }

    }

    /**
     * 重新计算门客能力+魂环buff
     */
    public boolean calHunLi(DouLuoDaLuUserData userData, List<DouLuoDaLuUserPatrons> userPatronsList) {
        boolean change = false;
        List<Integer> buffIdList = mergeHunHuan(userData);
        //固定值加成
        int addition = getHunLiFixedAddition(buffIdList);
        //千分比加成
        int permillage = getHunLiMilliAddition(buffIdList);
        long allHunLi = 0;
        if(userPatronsList != null) {
            for (DouLuoDaLuUserPatrons userPatrons : userPatronsList) {
                if (userData.getPatronsMap().containsKey(userPatrons.getPatronsId())) {
                    DouLuoDaLuUserPatrons oldPatrons = userData.getPatronsMap().get(userPatrons.getPatronsId());
                    oldPatrons.setPromotionId(userPatrons.getPromotionId());
                    oldPatrons.setSkinId(userPatrons.getSkinId());
                    oldPatrons.setPatronsLv(userPatrons.getPatronsLv());
                    if(oldPatrons.getAbility() != userPatrons.getAbility()){
                        change = true;
                        oldPatrons.setAbility(userPatrons.getAbility());
                        oldPatrons.setHunLi(calHunLi(oldPatrons.getAbility(), addition, permillage));
                    }
                }else {
                    userPatrons.setHunLi(calHunLi(userPatrons.getAbility(), addition, permillage));
                    userData.getPatronsMap().put(userPatrons.getPatronsId(), userPatrons);
                    change = true;
                }
            }
        }else {
            for (Map.Entry<Integer, DouLuoDaLuUserPatrons> patronsEntry : userData.getPatronsMap().entrySet()) {
                DouLuoDaLuUserPatrons userPatrons = patronsEntry.getValue();
                userPatrons.setHunLi(calHunLi(userPatrons.getAbility(), addition, permillage));
            }
            change = true;
        }
        if(change) {
            for (Map.Entry<Integer, DouLuoDaLuUserPatrons> patronsEntry : userData.getPatronsMap().entrySet()) {
                allHunLi += patronsEntry.getValue().getHunLi();
            }
            userData.setHunLi(allHunLi);
            userData.setPatronsNum(userData.getPatronsMap().size());
            userData.setFixedAddition(addition);
            userData.setAddition(permillage);
        }
        return change;
    }

    /**
     * 获取所有魂环
     */
    public List<Integer> mergeHunHuan(DouLuoDaLuUserData userData){
        List<Integer> buffIdList = new ArrayList<>();
        for (Map.Entry<Integer, Integer> buffEntry : userData.getHunHuanMap().entrySet()) {
            for (Integer i = 0; i < buffEntry.getValue(); i++) {
                buffIdList.add(buffEntry.getKey());
            }
        }
        return buffIdList;
    }

    /**
     * 魂环固定加成
     */
    public int getHunLiFixedAddition(List<Integer> buffIdList){
        int addition = 0;
        for (int buffId : buffIdList) {
            List<Integer> buffList = config.getHunHuanBuffMap().get(buffId);
            if(buffList != null && buffList.size() == 2){
                addition += buffList.get(0);
            }
        }
        return addition;
    }

    /**
     * 魂环千分比加成
     */
    public int getHunLiMilliAddition(List<Integer> buffIdList){
        int addition = 0;
        for (int buffId : buffIdList) {
            List<Integer> buffList = config.getHunHuanBuffMap().get(buffId);
            if(buffList != null && buffList.size() == 2){
                addition += buffList.get(1);
            }
        }
        return addition;
    }

    /**
     * 计算魂力
     * 基础 * （1 + 千分比）+ 固定加成
     */
    public long calHunLi(long ability, int addition, int permillage) {
        return BigDecimal.valueOf(ability).multiply(BigDecimal.valueOf(1000 + permillage)).divide(BigDecimal.valueOf(1000l), 0, BigDecimal.ROUND_UP).longValue() + addition;
    }

    /**
     * 刷新玩家体力
     */
    public void refreshUserEnergy(DouLuoDaLuUserData user, boolean forceUpdate){
        long now = System.currentTimeMillis() / 1000;
        long time = now - user.getEnergyLastTime();
        if (user.getEnergy() < config.ENERGY_MAX) {
            int timesCD = (int)(time / config.ENERGY_CD);
            if (timesCD > 0 ) {
                int times = timesCD * config.ENERGY_CD_NUM;
                if (times + user.getEnergy() < config.ENERGY_MAX) {
                    user.setEnergyLastTime(user.getEnergyLastTime() + timesCD * config.ENERGY_CD);
                    user.setEnergy(user.getEnergy() + times);
                }else {
                    user.setEnergyLastTime(now);
                    user.setEnergy(config.ENERGY_MAX);
                }
            }
        } else {
            if (forceUpdate) {
                user.setEnergyLastTime(now);
            }
        }

    }

    /**
     * 创建队伍
     */
    public DouLuoDaLuTeamData createTeam(String name, DouLuoDaLuUserData leader) {
        long now = System.currentTimeMillis() / 1000;
        DouLuoDaLuTeamData teamData = new DouLuoDaLuTeamData(activityId, groupId, maxTeamId.incrementAndGet());
        teamData.setCaptainId(leader.getUserId());
        teamData.setCaptainServerId(leader.getServerId());
        teamData.setName(name);
        teamData.setCreateTime(now);
        leader.setTeamId(teamData.getTeamId());
        leader.setLastCreateTime(now);
        addMember(teamData, leader);
        allTeamMap.put(teamData.getTeamId(), teamData);
        addServerTeam(teamData);
        addTeamChat(teamData, leader,3, eChatContentType.Common.getContentType(), name, now);

        updateTeamTotalEarn(teamData);
        //日志
        CrossAutoLogMgr.add(new LogDouLuoDaLuTeam(activityId, leader.getUserId(), teamData.getTeamId(), 1, 0));
        return teamData;
    }

    /**
     * 取消入隊申請
     * @param userData
     * @param isBroadcast
     */
    public void cancelApply(DouLuoDaLuUserData userData, boolean isBroadcast){
        List<Integer> list = new ArrayList(userData.getApplyJoinTeamMap().keySet());
        for(int teamId : list){
            DouLuoDaLuTeamData applyTeam = allTeamMap.get(teamId);
            if(null != applyTeam ){
                cancelApply(userData, applyTeam, isBroadcast);
            }
        }
    }

    public void cancelApply(DouLuoDaLuUserData user, DouLuoDaLuTeamData team, boolean isBroadcast) {
        // 移除联盟上面的申请
        team.removeApply(user.getUserId());
        // 移除玩家身上的记录
        user.removeApplyJoinTeam(team.getTeamId());
        if(isBroadcast){
            // 通知队长
            DouLuoDaLuUserData leader = allUserMap.get(team.getCaptainId());
            if(leader != null) {
                DouLuoDaLuProto.DouLuoDaLuApplyChangeEntity.Builder changeBuilder = CrossDouLuoDaLuMgr.buildApplyChangeEntity(1, null, user.getUserId());
                MessageHelper.sendPacket(leader.getServerId(), leader.getUserId(),
                        YanQuMessageUtils.buildMessage(ClientProtocol.U_DOU_LUO_DA_LU_BROADCAST_TEAM_APPLY, changeBuilder));
            }
        }

    }

    public void addDeleteTeam(DouLuoDaLuTeamData teamData){
        synchronized (deleteList){
            deleteList.add(teamData);
        }
    }

    /**
     * 添加成员
     * @param team
     * @param member
     */
    public void addMember(DouLuoDaLuTeamData team , DouLuoDaLuUserData member){
        long now = System.currentTimeMillis()/1000;
        team.getMemberList().put(member.getUserId(), now);
        team.setUpdateOption();
        member.setTeamId(team.getTeamId());

        if(team.getCaptainId() != member.getUserId()){
            addTeamChat(team, member,1, eChatContentType.Common.getContentType(), null, now);
        }
    }

    /**
     * 成员离开队伍
     * @param team
     * @param member
     * @param type  退出队伍的方式 1被踢 2解散 3主动离队
     */
    public void memberQuitTeam(DouLuoDaLuTeamData team, DouLuoDaLuUserData member, int type){
        team.removeMember(member.getUserId());
        member.setTeamId(0);
        int identity = (team.getCaptainId() == member.getUserId() ? 1: 0);
        long now = System.currentTimeMillis()/1000;
        if((type == 2 && team.getCaptainId() == member.getUserId()) || type == 3){
            member.setLastLeaveTime(now);
        }
        if(type != 2){
            addTeamChat(team, member,2, eChatContentType.Common.getContentType(), null, now);
        }
        if(type != 3 && member.getUserId() != team.getCaptainId()){
            //缓存
            if(!member.isEntry()) {
                member.setLeaveTip(new DouLuoDaLuTeamLeaveTip(type, team.getCaptainId(), team.getName()));
            }else {
                DouLuoDaLuProto.DouLuoDaLuLeaveInfoEntity.Builder leaveInfo = DouLuoDaLuProto.DouLuoDaLuLeaveInfoEntity.newBuilder();
                leaveInfo.setType(1);
                leaveInfo.setLeaderServerId(team.getCaptainServerId());
                leaveInfo.setTeamName(team.getName());
                DouLuoDaLuUserData leader = getAllUserMap().get(team.getCaptainId());
                leaveInfo.setLeaderName(leader.getUserBaseInfo().getNickName());

                //消息推送
                DouLuoDaLuProto.DouLuoDaLuOnLinePushTemp.Builder tempBuilder = DouLuoDaLuProto.DouLuoDaLuOnLinePushTemp.newBuilder();
                tempBuilder.setType(1);
                tempBuilder.addUser(member.getUserId());
                tempBuilder.setLeave(leaveInfo);
                pushMsg(member.getServerId(), tempBuilder);
            }
        }
    }

    /**
     * 推送通知
     */
    public void pushMsg(long serverId, DouLuoDaLuProto.DouLuoDaLuOnLinePushTemp.Builder tempBuilder){
        try {
            DouLuoDaLuProto.DouLuoDaLuOnLinePushMsg.Builder pushMsg = DouLuoDaLuProto.DouLuoDaLuOnLinePushMsg.newBuilder();
            pushMsg.setActivityId(activityId);
            pushMsg.addPush(tempBuilder);
            MessageHelper.sendPacket(serverId, 0, YanQuMessageUtils.buildMessage(Protocol.S_DOU_LUO_DA_LU_PUSH_MSG, pushMsg));
        }catch (Exception e){
            CrossDouLuoDaLuMgr.getLogger().error(e);
        }
    }


    /**
     * 广播协助记录攻击信息
     */
    public void broadcastHelpRecordAttackInfo(DouLuoDaLuTeamData team){
        List<DouLuoDaLuUserData> list = new ArrayList<>();
        for (Map.Entry<Long, Long> entry : team.getMemberList().entrySet()) {
            long uid = entry.getKey();
            DouLuoDaLuUserData ud = getAllUserMap().get(uid);
            if(ud != null){
                list.add(ud);
            }
        }
        broadcastHelpRecordAttackInfo(list, team);
    }

    /**
     * 广播协助记录攻击信息
     */
    public void broadcastHelpRecordAttackInfo(List<DouLuoDaLuUserData> list, DouLuoDaLuTeamData team){
        Map<Long, DouLuoDaLuHelpRecordData> recordDataMap = getHelpRecordDataMap(team);
        for (DouLuoDaLuUserData userData : list) {
            DouLuoDaLuProto.BroadcastDouLuoDaLuHelpRecordAttackInfoEntity.Builder sync = DouLuoDaLuProto.BroadcastDouLuoDaLuHelpRecordAttackInfoEntity.newBuilder();
            for (Map.Entry<Long, DouLuoDaLuHelpRecordData> dataEntry : recordDataMap.entrySet()) {
                DouLuoDaLuHelpRecordData recordData = dataEntry.getValue();
                DouLuoDaLuProto.DouLuoDaLuHelpRecordAttackInfoEntity.Builder attack = DouLuoDaLuProto.DouLuoDaLuHelpRecordAttackInfoEntity.newBuilder();
                attack.setRecordId(recordData.getId());
                DouLuoDaLuAttackInfo attackInfo = recordData.getHelpAttackMap().get(userData.getUserId());
                if(attackInfo != null){
                    attack.setTime(attackInfo.getAttackTime());
                }
                sync.addHelpRecordAttackInfos(attack);
            }
            MessageHelper.sendPacket(userData.getServerId(), userData.getUserId(), YanQuMessageUtils.buildMessage(ClientProtocol.U_DOU_LUO_DA_LU_BROADCAST_HELP_ATTACK_INFO, sync));
        }
    }

    /**
     *  新增聊天
     * @param team  队伍
     * @param user  玩家
     * @param type 类型 0玩家发言 1加入 2离开 3创建队伍 4协助信息(recordId|eventId  (|targetServerId|targetName|decoration） 玩家事件才有 )
     * @param content
     * @param now 发送时间
     */
    public void addTeamChat(DouLuoDaLuTeamData team, DouLuoDaLuUserData user, int type, int contentType, String content, long now){
        // 设置上限值
        WorldMessageProto.WorldMessageListMsg.Builder chatList = getTeamChat(team.getTeamId());
        if(chatList.getDataListCount() >= config.FIGHT_CHAT_LIMIT && chatList.getDataListCount() != 0){
            synchronized (chatList) {
                chatList.removeDataList(0);
            }
        }
        WorldMessageProto.WorldMessageTempMsg.Builder messageTempMsg = WorldMessageProto.WorldMessageTempMsg.newBuilder();
        // type 0 普通聊天 1加入 2离开 3创建队伍 4协助信息
        messageTempMsg.setType(type);
        messageTempMsg.setContentType(contentType);
        messageTempMsg.setUserId(user.getUserId());
        if(content != null){
            messageTempMsg.setContent(content);
        }
        messageTempMsg.setSendTime(now);
        PlayerProto.PlayerBaseTempMsg.Builder baseMsg = PlayerBasePb.parsePlayerBaseTempMsg(user.getUserBaseInfo());
        messageTempMsg.setPlayerBaseData(baseMsg);
        synchronized (chatList){
            chatList.addDataList(messageTempMsg.build());
        }
        DouLuoDaLuProto.DouLuoDaLuTeamChatEntity.Builder builder = DouLuoDaLuProto.DouLuoDaLuTeamChatEntity.newBuilder();
        builder.setMsg(messageTempMsg);
        for (DouLuoDaLuHelpRecordData recordData : getHelpRecordDataMap(team).values()){
            //只能看到同区域的求助
            //if(recordData.getRegionId() != user.getRegionId()){
            //    continue;
            //}
            //当前正在求助的记录id
            builder.addRecordList(DouLuoDaLuProto.DouLuoDaLuHelpSimpleRecordEntity.newBuilder().setId(recordData.getId()).setRecordTime(recordData.getRecordTime()));
        }
        // 通知在线的队友（不在线的就忽略）
        for (Map.Entry<Long, Long> longEntry : team.getMemberList().entrySet()) {
            long memberId = longEntry.getKey();
            DouLuoDaLuUserData member = allUserMap.get(memberId);
            if(member != null){
                MessageHelper.sendPacket(member.getServerId(), member.getUserId(), YanQuMessageUtils.buildMessage(ClientProtocol.U_DOU_LUO_DA_LU_BROADCAST_TEAM_CHAT, builder));
            }
        }
    }

    /**
     * 队伍列表（当前分页数据）- 组队期间（按赚钱排名）
     */
   public List<DouLuoDaLuTeamData> getTeamDataList(int page, int type, long userId, long serverId){
       List<DouLuoDaLuTeamData> result = new ArrayList<>();
       List<DouLuoDaLuTeamData> tempList = new ArrayList<>();
       List<DouLuoDaLuTeamData> teamDataList;
       if(type == 0){
           teamDataList = new ArrayList<>(allTeamMap.values());
       }else {
           //分组跨服
           int groupId = CrossUnionServerGroupMgr.getGroupIdByServerId(serverId);
           Set<Long> serverSet = CrossUnionServerGroupMgr.getGroupServer(groupId);
           teamDataList = new ArrayList<>();
           for (long sid : serverSet) {
               List<DouLuoDaLuTeamData> list = serverTeamMap.get(sid);
               if(list != null){
                   teamDataList.addAll(list);
               }
           }
           //teamDataList = new ArrayList<>(serverTeamMap.get(serverId));
       }
       for (DouLuoDaLuTeamData teamData : teamDataList) {
           if(teamData.getApplyList().containsKey(userId)){
               //过滤已申请
               continue;
           }
           if(teamData.getMemberList().size() < 4){
               tempList.add(teamData);
           }
       }
       tempList.sort((t1,t2)->{
           if(t1.getTotalEarn() != t2.getTotalEarn()){
               return Long.compare(t2.getTotalEarn(), t1.getTotalEarn());
           }else {
               return Long.compare(t1.getCreateTime(), t2.getCreateTime());
           }
       });
       page = Math.max(0, page);
       if(page == 0){
           // 优先下发已申请的队伍
           DouLuoDaLuUserData userData = this.getAllUserMap().get(userId);
           if(userData != null) {
               for (int teamId : userData.getApplyJoinTeamMap().keySet()) {
                   DouLuoDaLuTeamData team = allTeamMap.get(teamId);
                   if (team != null) {
                       result.add(team);
                   }
               }
           }
       }
       int startIndex = (PAGE_SIZE * page);
       int endIndex = startIndex + PAGE_SIZE;
       for (int i = startIndex; i < endIndex; i++) {
           if(i > (tempList.size() - 1)){
               break;
           }
           result.add(tempList.get(i));
       }
       return result;
   }

    /**
     * 检查队伍重名
     */
    public boolean checkTeamNameSame(String name) {
        for (Map.Entry<Integer, DouLuoDaLuTeamData> teamDataEntry : allTeamMap.entrySet()) {
            DouLuoDaLuTeamData teamData = teamDataEntry.getValue();
            if (Objects.equals(teamData.getName(), name)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 是否处在组队期
     * @return
     */
    public boolean isCreateTeamPeriod(){
        ActivityInfo activityInfo = ActivityMgr.getActivityInfo(activityId);
        if(activityInfo == null){
            return false;
        }
        int now = DateHelper.getCurrentSecond();
        long createTeamEndTime = activityInfo.getBeginTime() + config.CREATE_TEAM_TIME * DateHelper.MINUTE_SECONDS;
        if(now < activityInfo.getBeginTime() || now >= createTeamEndTime){
            return false;
        }
        return true;
    }

    /**
     * 是否处在组队期最后n分钟
     * @return
     */
    public boolean isCreateTeamPeriodLastNMin(int n){
        ActivityInfo activityInfo = ActivityMgr.getActivityInfo(activityId);
        int now = DateHelper.getCurrentSecond();
        if(activityInfo == null){
            return false;
        }
        long createTeamEndTime = activityInfo.getBeginTime() + config.CREATE_TEAM_TIME * DateHelper.MINUTE_SECONDS;
        //当前大于组队期,或者组队期最后组队期最后n分钟
        if(now > (createTeamEndTime - n * DateHelper.MINUTE_SECONDS)){
            return true;
        }
        return false;
    }

    /**
     * 获取当前协助记录（每个玩家一条记录）
     */
    public Map<Long, DouLuoDaLuHelpRecordData> getHelpRecordDataMap(DouLuoDaLuTeamData team) {
        Map<Long, DouLuoDaLuHelpRecordData> helpRecordDataMap = new HashMap<>();
        for (Map.Entry<Long, Long> longEntry : team.getMemberList().entrySet()) {
            long memberId = longEntry.getKey();
            DouLuoDaLuUserData userData = getAllUserMap().get(memberId);
            if(userData != null){
                DouLuoDaLuHelpRecordData recordData = userData.getCurrentHelpRecordData();
                if(recordData != null){
                    helpRecordDataMap.put(recordData.getId(), recordData);
                }
            }
        }
        return helpRecordDataMap;
    }

    /**
     * 森林-伤害计算
     */
    public void attackDamage(long attack, long blood, DouLuoEventHandleResult handleResult){
        long remainBlood = Math.max(0, blood - attack);
        boolean isKill = (remainBlood <= 0);
        long damage = isKill ? blood : attack;

        handleResult.setKill(isKill);
        handleResult.setBlood(remainBlood);
        handleResult.setDamage(damage);
    }

    /**
     * 有可领取的协助奖励
     *
     */
    public boolean hasReceiveHelpReward(DouLuoDaLuUserData userData) {
        List<DouLuoDaLuHelpRecordData> list = helpRecordDataMap.get(userData.getUserId());
        if(list == null || list.size() == 0){
            return false;
        }
        for (int i = 0; i < list.size(); i++) {
            DouLuoDaLuHelpRecordData recordData = list.get(i);
            if(recordData.getUserId() == userData.getUserId() && recordData.getKilledUserId() > 0 && !recordData.isReceived()){
                return true;
            }
        }
        return false;
    }

    /**
     * 有可协助的记录(可攻击，考虑CD)
     */
    public boolean hasHelpAction(DouLuoDaLuUserData userData, DouLuoDaLuTeamData teamData){
        boolean hasHelpAction = false;
        Map<Long, DouLuoDaLuHelpRecordData> helpRecordDataMap = getHelpRecordDataMap(teamData);
        int now = DateHelper.getCurrentSecond();
        for (Map.Entry<Long, DouLuoDaLuHelpRecordData> dataEntry : helpRecordDataMap.entrySet()) {
            DouLuoDaLuHelpRecordData recordData = dataEntry.getValue();
            DouLuoDaLuAttackInfo attackInfo = recordData.getHelpAttackMap().get(userData.getUserId());
            if(attackInfo == null){
                hasHelpAction = true;
                break;
            }else {
                if(now - attackInfo.getAttackTime() >= getConfig().FOREST_ATTACK_CD){
                    hasHelpAction = true;
                    break;
                }
            }
        }
        return hasHelpAction;
    }

    /**
     * 检查红点
     */
    public void checkUserRedHot(DouLuoDaLuUserData userData, DouLuoDaLuTeamData teamData){
        try {
            if (teamData == null) {
                //个人
                boolean hasHelpReward = hasReceiveHelpReward(userData);
                DouLuoDaLuTeamData team = getAllTeamMap().get(userData.getTeamId());
                boolean hasHelpAction = false;
                if (team != null) {
                    hasHelpAction = hasHelpAction(userData, team);
                }
                DouLuoDaLuProto.DouLuoDaLuRedDotSyncMsg.Builder redDot = DouLuoDaLuProto.DouLuoDaLuRedDotSyncMsg.newBuilder();
                redDot.setHelpReward(hasHelpReward);
                redDot.setHelpAction(hasHelpAction);
                syncUserRedDot(userData, redDot);
            } else {
                //队伍
                for (Map.Entry<Long, Long> longEntry : teamData.getMemberList().entrySet()) {
                    long uid = longEntry.getKey();
                    DouLuoDaLuUserData user = getAllUserMap().get(uid);
                    if (user != null) {
                        boolean hasHelpAction = hasHelpAction(user, teamData);
                        boolean hasHelpReward = hasReceiveHelpReward(user);
                        DouLuoDaLuProto.DouLuoDaLuRedDotSyncMsg.Builder redDot = DouLuoDaLuProto.DouLuoDaLuRedDotSyncMsg.newBuilder();
                        redDot.setHelpReward(hasHelpReward);
                        redDot.setHelpAction(hasHelpAction);
                        syncUserRedDot(user, redDot);
                    }
                }
            }
        }catch (Exception e){
            CrossDouLuoDaLuMgr.getLogger().error("checkUserRedHot", e);
        }
    }

    public void syncBaseInfoToServer(DouLuoDaLuUserData userData){
        DouLuoDaLuProto.DouLuoDaLuSyncUserDataToServerMsg.Builder sync = DouLuoDaLuProto.DouLuoDaLuSyncUserDataToServerMsg.newBuilder();
        sync.setRegionId(userData.getRegionId());
        sync.setTeamId(userData.getTeamId());
        sync.setScore1(userData.getScore());
        if(userData.getBattleData() != null){
            sync.setScore2(userData.getBattleData().getScore());
        }
        YanQuMessage yanQuMessage = YanQuMessageUtils.buildMessage(Protocol.S_DOU_LUO_DA_LU_SYNC_USER_DATA_TO_SERVER, sync);
        MessageHelper.sendPacket(userData.getServerId(), userData.getUserId(), yanQuMessage);
    }

    /**
     * 按权重随机区域内的事件
     */
    public DouLuoDaLuEventInfo randomRegionEvent(DouLuoDaLuUserData userData, boolean excludePlayerEvent, long stoneNum) {
        DouLuoDaLuRegionInfo regionInfo = config.getRegionInfo(userData.getRegionId());
        if(regionInfo == null){
            return null;
        }
        List<Integer> eventList = new ArrayList<>();
        List<Integer> weightList = new ArrayList<>();

        if(!excludePlayerEvent){
            //CD保护,不触发真人事件
            if(userData.getEntryRegionTime() > 0 && DateHelper.getCurrentSecond() - userData.getEntryRegionTime() < config.FOREST_PROTECT_TIME){
                excludePlayerEvent = true;
            }
        }

        //是否七怪赠礼保底
        boolean mustSevenSecurity = config.hasSevenSecurity(regionInfo.getRegionId(), userData.getRegionEventMap().getOrDefault(regionInfo.getRegionId(), 0));
        if(mustSevenSecurity){
            //只留七怪事件
            for (int i = 0; i < regionInfo.getEventIdList().size(); i++) {
                int eventId = regionInfo.getEventIdList().get(i);
                if(!config.getSevenEventId().contains(eventId)){
                    continue;
                }
                eventList.add(eventId);
                weightList.add(regionInfo.getEventWeightList().get(i));
            }
        } else if(!excludePlayerEvent){
            for (int i = 0; i < regionInfo.getEventIdList().size(); i++) {
                Integer eventId = regionInfo.getEventIdList().get(i);
                Integer weight = regionInfo.getEventWeightList().get(i);
                if (config.getSevenEventId().contains(eventId)) {
                    weight = config.getSevenEventWeight(weight, stoneNum);
                }
                eventList.add(eventId);
                weightList.add(weight);
            }
        }else {
            //v4.2  真人事件概率平分给非七怪事件
            //真人事件权重
            int playerWeight = 0;
            //非真人事件、非七怪事件的其他事件个数
            int eventNum = 0;
            //排除真人事件
            for (int i = 0; i < regionInfo.getEventIdList().size(); i++) {
                int eventId = regionInfo.getEventIdList().get(i);
                if(config.getPlayerEventId().contains(eventId)){
                    playerWeight += regionInfo.getEventWeightList().get(i);
                    continue;
                }
                if(!config.getSevenEventId().contains(eventId)){
                    eventNum++;
                }
                eventList.add(eventId);
                Integer weight = regionInfo.getEventWeightList().get(i);
                if (config.getSevenEventId().contains(eventId)) {
                    weight = config.getSevenEventWeight(weight, stoneNum);
                }
                weightList.add(weight);
            }
            //分摊前事件与权重
            if(CrossDouLuoDaLuMgr.getLogger().isDebugEnabled()){
                //CrossDouLuoDaLuMgr.getLogger().debug("-----分摊前事件与权重-----");
                for (int i = 0; i < eventList.size(); i++) {
                    //CrossDouLuoDaLuMgr.getLogger().debug("-----事件{}：权重{}-----", eventList.get(i), weightList.get(i));
                }
            }
            //平均分摊权重
            int agv = 0;
            if(eventNum > 0) {
                agv = playerWeight / eventNum + 1;
            }
            //CrossDouLuoDaLuMgr.getLogger().debug("---------------真人权重：{}， 其他事件（非七怪）个数{}， 平均分摊权重 {}", playerWeight, eventNum, agv);
            for (int i = 0; i < eventList.size(); i++) {
                int eid = eventList.get(i);
                if(config.getSevenEventId().contains(eid)){
                    continue;
                }
                weightList.set(i, agv + weightList.get(i));
            }
            if(CrossDouLuoDaLuMgr.getLogger().isDebugEnabled()){
                //CrossDouLuoDaLuMgr.getLogger().debug("-----分摊后事件与权重-----");
                for (int i = 0; i < eventList.size(); i++) {
                    //CrossDouLuoDaLuMgr.getLogger().debug("-----事件{}：权重{}-----", eventList.get(i), weightList.get(i));
                }
            }
        }
        int idx = RandomHelper.getRandomIndexByWeight(weightList, random);
        if(idx == -1 || idx >= eventList.size()){
            return null;
        }
        int eventId = eventList.get(idx);
        DouLuoDaLuEventInfo eventInfo = config.getEventInfo(eventId);
        //CrossDouLuoDaLuMgr.getLogger().debug("---------------{}: explore {}-{}", userData.getUserId(), eventInfo.getEventId(), eventInfo.getEventType());
        return eventInfo;
    }


    /**
     * 按权重随机区域内的事件  6.2优化
     * @param exchangeIdList 非空时 只会随机出这里面的事件
     */
    public DouLuoDaLuEventInfo randomRegionEventNew(DouLuoDaLuUserData userData, List<Integer> exchangeIdList, long stoneNum,long lowBoxConsumeCount, long highBoxConsumeCount) {
        DouLuoDaLuRegionInfo regionInfo = config.getRegionInfo(userData.getRegionId());
        if (regionInfo == null) {
            return null;
        }
        List<Integer> eventList = new ArrayList<>();
        List<Integer> weightList = new ArrayList<>();

        // 需要排除的事件
        List<Integer> excludeEventId = new ArrayList<>();

        //CD保护,不触发真人事件
        if (userData.getEntryRegionTime() > 0 && DateHelper.getCurrentSecond() - userData.getEntryRegionTime() < config.FOREST_PROTECT_TIME) {
            excludeEventId.add(config.getEventInfoList(eDouLuoDaLuEventType.PlayerEvent.getIntValue()).get(0).getEventId());
        }

        //是否七怪赠礼保底
        boolean mustSevenSecurity = config.hasSevenSecurity(regionInfo.getRegionId(), userData.getRegionEventMap().getOrDefault(regionInfo.getRegionId(), 0));
        if (mustSevenSecurity) {
            //只留七怪事件
            for (int i = 0; i < regionInfo.getEventIdList().size(); i++) {
                int eventId = regionInfo.getEventIdList().get(i);
                if (!config.getSevenEventId().contains(eventId)) {
                    continue;
                }
                eventList.add(eventId);
                weightList.add(regionInfo.getEventWeightList().get(i));
            }
        } else {
            for (int i = 0; i < regionInfo.getEventIdList().size(); i++) {
                Integer eventId = regionInfo.getEventIdList().get(i);
                // 不在列表的不需要随机
                if (!exchangeIdList.isEmpty() && !exchangeIdList.contains(eventId)) {
                    continue;
                }
                // 需要排除的事件
                if (excludeEventId.contains(eventId)) {
                    continue;
                }
                Integer weight = regionInfo.getEventWeightList().get(i);
                if (config.getSevenEventId().contains(eventId)) {
                    weight = config.getSevenEventWeight(weight, stoneNum);
                }
                eventList.add(eventId);
                weightList.add(weight);
            }
        }
        int idx = RandomHelper.getRandomIndexByWeight(weightList, random);
        if (idx == -1 || idx >= eventList.size()) {
            return null;
        }
        int eventId = eventList.get(idx);
        DouLuoDaLuEventInfo eventInfo = config.getEventInfo(eventId);
        //CrossDouLuoDaLuMgr.getLogger().debug("---------------{}: explore {}-{}", userData.getUserId(), eventInfo.getEventId(), eventInfo.getEventType());
        // 如果是宝箱判断下是否符合
        if (config.getEventInfo(eventInfo.getEventId()).getEventType() == eDouLuoDaLuEventType.MonsterBoxEvent.getIntValue()) {
            if (eventInfo.getEventId() == 30001) {
                // 判断下是否需要替换
                Integer lowBoxCount = userData.getBoxMap().getOrDefault(Integer.parseInt(config.getEventInfo(30001).getTargetId()), 0);
                if (lowBoxCount - lowBoxConsumeCount >= config.getEventBoxExchangeCond().get(0)) {
                    // 重随
                    return randomRegionEventNew(userData, config.getEventLowBoxExchangeId(), stoneNum, lowBoxConsumeCount, highBoxConsumeCount);
                }
            } else if (eventInfo.getEventId() == 30002) {
                // 判断下是否需要替换
                Integer highBoxCount = userData.getBoxMap().getOrDefault(Integer.parseInt(config.getEventInfo(30002).getTargetId()), 0);
                if (highBoxCount - highBoxConsumeCount >= config.getEventBoxExchangeCond().get(1)) {
                    // 重随
                    return randomRegionEventNew(userData, config.getEventHighBoxExchangeId(), stoneNum, lowBoxConsumeCount, highBoxConsumeCount);
                }
            }
        }
        return eventInfo;
    }


    /**
     * 获取id血量
     */
    public long getNpcBlood(int eventId) {
        DouLuoDaLuNpcBloodData bloodData = npcBlood.get(eventId);
        long minBlood = (bloodData.getBlood() * config.floatValueList.get(0) + 100 - 1) / 100;
        long maxBlood = (bloodData.getBlood() * config.floatValueList.get(1) + 100 - 1) / 100;
        long diffBlood = 0;
        if (maxBlood > minBlood) {
            diffBlood = maxBlood - minBlood;
            diffBlood = RandomHelper.nextLong(diffBlood);
        }
        return minBlood + diffBlood;
    }

    /**
     * 初始魂兽动态血量
     */
    public void initMonsterDynamicBlood(boolean refresh){
        List<DouLuoDaLuEventInfo> monsterEvent = config.getEventInfoList(eDouLuoDaLuEventType.MonsterEvent.getIntValue());
        if(npcBlood.size() != monsterEvent.size() || refresh){
            synchronized (npcBlood){
                if(npcBlood.size() != monsterEvent.size() || refresh) {
                    long now = System.currentTimeMillis();
                    CrossDouLuoDaLuMgr.getLogger().debug("------------------------init monster dynamic begin. {}, refresh {}", activityId, refresh);
                    Map<Integer, DouLuoDaLuNpcBloodData> npcBloodTemp = new ConcurrentHashMap<>();
                    //所有玩家按魂力值倒叙
                    List<DouLuoDaLuUserData> userList = getDouLuoDaLuUserDataInTeamDesc();
//                    CrossDouLuoDaLuMgr.getLogger().debug("user ability");
//                    for (DouLuoDaLuUserData data : userList) {
//                        CrossDouLuoDaLuMgr.getLogger().debug("{},{}", data.getUserId(), data.getHunLi());
//                    }
                    long upEventBlood = 0;
                    Date nowDate = new Date();
                    for (DouLuoDaLuUserData luUserData : userList) {
                        CrossAutoLogMgr.add(new LogDouLuoDaLuUserHunLi(activityId, luUserData.getUserId(), luUserData.getHunLi(), nowDate));
                    }
                    for (DouLuoDaLuEventInfo eventInfo : monsterEvent) {

                        List<String> paramList = StringUtils.stringToStringList(eventInfo.getParam(), "\\|");
                        if(paramList.size() != 3){
                            continue;
                        }
                        // 基数1 血量基数1=对应名次区间内所有玩家的门客魂力总值的平均值
                        // 取玩家的能力区间
                        List<Integer> playerSection = StringUtils.stringToIntegerList(paramList.get(0), ";");
                        if(playerSection.size() != 2){
                            CrossDouLuoDaLuMgr.getLogger().error("{},{}", eventInfo.getEventId(), eventInfo.getParam());
                            continue;
                        }
                        int rank1 = playerSection.get(0);
                        int rank2 = playerSection.get(1);
                        CrossDouLuoDaLuMgr.getLogger().debug("baseValue1, {} to {}", rank1, rank2);
                        DouLuoDaLuCalBloodBaseInfo baseValue1 = getRangeAverageResult(rank1, rank2, userList);

                        // 基数2 血量基数2=百分比取值对应的玩家门客魂力总值
                        List<Integer> playerSection2 = StringUtils.stringToIntegerList(paramList.get(1), ";");
                        int rank3 = (userList.size() * playerSection2.get(0) + 1000 - 1) / 1000;
                        int rank4 = (userList.size() * playerSection2.get(1) + 1000 - 1) / 1000;
                        CrossDouLuoDaLuMgr.getLogger().debug("baseValue2, {} to {}", rank3, rank4);
                        DouLuoDaLuCalBloodBaseInfo baseValue2 = getRangeAverageResult(rank3, rank4, userList);

                        // 基数3 血量基数3=保底值
                        long baseValue3 = Long.valueOf(paramList.get(2));

                        // 基数4
                        long baseValue4 = (upEventBlood * config.FOREST_CAlC_HP_ADD_PAR + 1000 - 1) / 1000;

                        long blood = baseValue1.agev > baseValue2.agev ? baseValue1.agev : baseValue2.agev;
                        blood = blood > baseValue3 ? blood : baseValue3;
                        blood = blood > baseValue4 ? blood : baseValue4;

                        DouLuoDaLuNpcBloodData bloodData = npcBlood.get(eventInfo.getEventId());
                        if(bloodData == null){
                            bloodData = new DouLuoDaLuNpcBloodData(activityId, groupId, eventInfo.getEventId());
                        }
                        bloodData.setBlood(blood);
                        bloodData.setUpdateTime(now);
                        bloodData.setUserNum(userList.size());

                        bloodData.setBaseValue1(baseValue1.agev);
                        bloodData.setStartRank1(baseValue1.startRank);
                        bloodData.setEndRank1(baseValue1.endRank);
                        bloodData.setEarnSum1(baseValue1.all);
                        bloodData.setNum1(baseValue1.num);

                        bloodData.setBaseValue2(baseValue2.agev);
                        bloodData.setStartRank2(baseValue2.startRank);
                        bloodData.setEndRank2(baseValue2.endRank);
                        bloodData.setEarnSum2(baseValue2.all);
                        bloodData.setNum2(baseValue2.num);

                        bloodData.setBaseValue3(baseValue3);
                        bloodData.setBaseValue4(baseValue4);

                        npcBloodTemp.put(eventInfo.getEventId(), bloodData);
                        upEventBlood = blood;
                        CrossDouLuoDaLuMgr.getLogger().info("activityId：{},eventId:{},baseValue1:{},baseValue2:{},baseValue3:{},baseValue4:{},final:{}", activityId, eventInfo.getEventId(), baseValue1.agev,
                                baseValue2.agev, baseValue3, baseValue4, blood);

                        addLogDouLuoDaLuNpcBloodData(bloodData);
                    }
                    npcBlood.putAll(npcBloodTemp);
                    CrossDouLuoDaLuMgr.getLogger().info("------------------------init monster dynamic success. {}", activityId);

                }
            }
        }
    }

    /**
     * 获取玩家门客总能力区间排名的平均能力
     */
    public DouLuoDaLuCalBloodBaseInfo getPatronsAverageAbility(int rankStart, int rankEnd) {
        List<DouLuoDaLuUserData> userList = getDouLuoDaLuUserDataInTeamDesc();
        DouLuoDaLuCalBloodBaseInfo result = getRangeAverageResult(rankStart, rankEnd, userList);
        return result;
    }

    /**
     * 获取区间平均值
     */
    private DouLuoDaLuCalBloodBaseInfo getRangeAverageResult(int rankStart, int rankEnd, List<DouLuoDaLuUserData> userList) {
        DouLuoDaLuCalBloodBaseInfo bloodBaseInfo = new DouLuoDaLuCalBloodBaseInfo();
        int num = 0;
        long all = 0;
        int size = userList.size();
        for (int j = rankStart; j <= rankEnd; j++) {
            if (j > size) {
                break;
            }
            int index = j - 1;
            if (index < 0) {
                // 防止配0的情况
                continue;
            }
            DouLuoDaLuUserData userData = userList.get(index);
            all += userData.getHunLi();
            num++;
        }
        long result = 0;
        if (num > 0) {
            result = (all + num - 1) / num;
        }
        bloodBaseInfo.startRank = rankStart;
        bloodBaseInfo.endRank = rankEnd;
        bloodBaseInfo.num = num;
        bloodBaseInfo.all = all;
        bloodBaseInfo.agev = result;
        CrossDouLuoDaLuMgr.getLogger().info("startRank :{},endRank:{},num:{},all:{},agv:{}", rankStart, rankEnd, num, all, result);
        return bloodBaseInfo;
    }

    /**
     * 所有玩家按能力值倒叙
     */
    private List<DouLuoDaLuUserData> getDouLuoDaLuUserDataInTeamDesc() {
        List<DouLuoDaLuUserData> tempList = new ArrayList<>(getAllUserMap().values());
        List<DouLuoDaLuUserData> userList = new ArrayList<>();
        for (DouLuoDaLuUserData userData : tempList) {
            if (userData.getTeamId() > 0) {
                userList.add(userData);
            }
        }
        userList.sort(new Comparator<DouLuoDaLuUserData>() {
            @Override
            public int compare(DouLuoDaLuUserData o1, DouLuoDaLuUserData o2) {
                return -Long.compare(o1.getHunLi(), o2.getHunLi());
            }
        });
        return userList;
    }

    /**
     * 森林纯随机不是商会成员、队伍的玩家，及保护CD
     */
    public DouLuoDaLuUserData randomRegionPlayer(DouLuoDaLuUserData userData, DouLuoDaLuTeamData teamData) {
        Map<Long, DouLuoDaLuUserData> userMap = areaUserMap.get(userData.getRegionId());
        if(userMap == null || userMap.size() == 0){
            return null;
        }
        int now = DateHelper.getCurrentSecond();
        String userUnionUid = CrossDouLuoDaLuMgr.getUserActivityUnionUid(userData.getActivityId(), userData.getUserId());
        List<DouLuoDaLuUserData> userList = new ArrayList<>();
        for (Map.Entry<Long, DouLuoDaLuUserData> userDataEntry : userMap.entrySet()) {
            if(userDataEntry.getValue().getTeamId() == 0){
                continue;
            }
            String findUnionUid = CrossDouLuoDaLuMgr.getUserActivityUnionUid(userDataEntry.getValue().getActivityId(), userDataEntry.getValue().getUserId());
            if(findUnionUid.equals(userUnionUid)
                    && !StringUtils.isNullOrEmpty(userUnionUid)){
                continue;
            }
            if(userData.getTeamId() == userDataEntry.getValue().getTeamId()){
                continue;
            }
            //保护CD
            if(userDataEntry.getValue().getEntryRegionTime() > 0 && now - userDataEntry.getValue().getEntryRegionTime() < config.FOREST_PROTECT_TIME){
                continue;
            }
            userList.add(userDataEntry.getValue());
        }
        if(userList.size() == 0){
            return null;
        }
        int idx = random.nextInt(userList.size());
        return userList.get(idx);
    }

    public List<DouLuoDaLuHelpRecordData> getHelpRecordDataList(long userId, boolean newIfNull) {
        List<DouLuoDaLuHelpRecordData> result = helpRecordDataMap.get(userId);
        if(result == null && newIfNull){
            helpRecordDataMap.put(userId, new ArrayList<>());
            result = helpRecordDataMap.get(userId);
        }
        return result;
    }

    public void addServerTeam(DouLuoDaLuTeamData teamData){
        List<DouLuoDaLuTeamData> list = serverTeamMap.get(teamData.getCaptainServerId());
        if(list == null){
            serverTeamMap.put(teamData.getCaptainServerId(), new ArrayList<>());
            list = serverTeamMap.get(teamData.getCaptainServerId());
        }
        list.add(teamData);
    }

    public void changeTeamRank(DouLuoDaLuTeamData teamData) {
        DouLuoDaLuUserData leader = getAllUserMap().get(teamData.getCaptainId());
        TeamBaseInfo teamBaseInfo = new TeamBaseInfo();
        teamBaseInfo.setUserBaseInfo(leader.getUserBaseInfo());
        teamBaseInfo.setCaptainId(leader.getUserId());
        teamBaseInfo.setTeamName(teamData.getName());
        if(leader == null){
            return;
        }
        BigInteger value = getTeamScore(teamData);
        ActivityTeamRankMgr.changeActivityTeamRank(activityId, eGamePlayerEventType.DouLuoDaLuPhaseTwoTeamScoreCrossRank.getValue(),
                teamData.getTeamId(), teamData.getCaptainServerId(), value, teamBaseInfo , "", groupId);
    }

    public BigInteger getTeamScore(DouLuoDaLuTeamData teamData) {
        BigInteger value = BigInteger.ZERO;
        for (Map.Entry<Long, Long> entry : teamData.getMemberList().entrySet()) {
            DouLuoDaLuPatronsBattleData battleData = getBattleDataMap().get(entry.getKey());
            if(battleData != null){
                value = value.add(BigInteger.valueOf(battleData.getScore()));
            }
        }
        return value;
    }

    public void changeTeamRank(int teamId){
        DouLuoDaLuTeamData teamData = getAllTeamMap().get(teamId);
        if(teamData != null){
            changeTeamRank(teamData);
        }
    }

    /**
     * 添加事件日志(玩家完成)
     */
    public DouLuoDaLuEventNoticeData addEventNotice(DouLuoDaLuUserData userData, DouLuoDaLuEventInfo eventInfo, int monsterId, String rewards, String consume, List<String> params, DouLuoDaLuUserData enemy,
                                                    int attackType, DouLuoDaLuUserData friend){
        DouLuoDaLuEventNoticeData noticeData = new DouLuoDaLuEventNoticeData(activityId, groupId, userData.getUserId());
        noticeData.setType(eventInfo.getEventType());
        noticeData.setRewards(rewards);
        if(!StringUtils.isNullOrEmpty(consume)) {
            noticeData.setConsume(consume);
        }
        noticeData.setMonsterId(monsterId);
        if(params != null && params.size() > 0) {
            noticeData.setParamList(params);
        }
        noticeData.setUserBaseInfo(userData.getUserBaseInfo());
        noticeData.setEventId(eventInfo.getEventId());
        noticeData.setRegionId(userData.getRegionId());

        if(enemy != null){
            noticeData.setEnemyBaseInfo(enemy.getUserBaseInfo());
        }
        if(friend != null) {
            noticeData.setFriendBaseInfo(friend.getUserBaseInfo());
        }
        noticeData.setAttackType(attackType);
        noticeData.setLogTime(System.currentTimeMillis());
        addEventNotice(noticeData);

        //我的事件日志
        syncEventLog(userData, noticeData);

        return noticeData;
    }

    public void syncEventLog(DouLuoDaLuUserData userData, DouLuoDaLuEventNoticeData noticeData) {
        //发送给区服,个人日志
        DouLuoDaLuProto.DouLuoDaLuUploadEventNoticeMsg.Builder battleNoticeBuilder = DouLuoDaLuProto.DouLuoDaLuUploadEventNoticeMsg.newBuilder();
        battleNoticeBuilder.setActivityId(activityId);
        battleNoticeBuilder.setEventNotice(DouLuoDaLuPb.getEventNoticeBuilder(noticeData));
        YanQuMessage yanQuMessage = YanQuMessageUtils.buildMessage(Protocol.S_DOU_LUO_DA_LU_EVENT_LOG_SYNC, battleNoticeBuilder);
        MessageHelper.sendPacket(userData.getServerId(), userData.getUserId(), yanQuMessage);
    }

    public void syncUserRedDot(DouLuoDaLuUserData userData, DouLuoDaLuProto.DouLuoDaLuRedDotSyncMsg.Builder redDot){
        YanQuMessage yanQuMessage = YanQuMessageUtils.buildMessage(Protocol.U_DOU_LUO_DA_LU_RED_DOT_SYNC, redDot);
        MessageHelper.sendPacket(userData.getServerId(), userData.getUserId(), yanQuMessage);
    }

    /**
     * 森林公告跑马灯
     */
    public void syncDouLuoDaLuEventNotice(DouLuoDaLuEventNoticeData noticeData) {
        DouLuoDaLuProto.SyncDouLuoDaLuEventNoticeMsg.Builder battleNoticeBuilder = DouLuoDaLuProto.SyncDouLuoDaLuEventNoticeMsg.newBuilder();
        battleNoticeBuilder.setEventNotice(DouLuoDaLuPb.getEventNoticeBuilder(noticeData));
        battleNoticeBuilder.setGroupId(groupId);
        YanQuMessage yanQuMessage = YanQuMessageUtils.buildMessage(Protocol.S_DOU_LUO_DA_LU_EVENT_SYNC_NOTICE, battleNoticeBuilder);
        CrossDouLuoDaLuMgr.broadcastActivityServerList(activityId, yanQuMessage);
    }

    public void addEventNotice(DouLuoDaLuEventNoticeData noticeData){
        noticeData.setInsertOption();
        synchronized (eventNoticeDataList){
            while(eventNoticeDataList.size() > config.FIGHT_LOG_LIMIT){
                eventNoticeDataList.remove(0);
            }
            eventNoticeDataList.add(noticeData);
        }
    }

    public void addBattleNotice(DouLuoDaLuBattleNoticeData noticeData){
        noticeData.setInsertOption();
        synchronized (battleNoticeDataList){
            while(battleNoticeDataList.size() > config.FIGHT_LOG_LIMIT){
                battleNoticeDataList.remove(0);
            }
            battleNoticeDataList.add(noticeData);
        }
    }

    /**
     * 添加宝库日志
     */
    public void uploadRecord(int rewardId, DouLuoDaLuUserData userData, int type) {
        DouLuoDaLuTryTrainRecordData data = new DouLuoDaLuTryTrainRecordData(activityId, groupId, userData.getUserId());
        data.setUserBaseInfo(userData.getUserBaseInfo());
        data.setRewardId(rewardId);
        data.setTime(System.currentTimeMillis());

        synchronized (recordList) {
            while(recordList.size() > config.FIGHT_LOG_LIMIT){
                recordList.remove(0);
            }
            recordList.add(data);
        }

        // 同步到区服
        DouLuoDaLuProto.SyncDouLuoDaLuTryTrainRecordRespMsg.Builder builder = DouLuoDaLuProto.SyncDouLuoDaLuTryTrainRecordRespMsg.newBuilder();
        builder.setRecord(DouLuoDaLuPb.parseTryTrainMsg(data));
        YanQuMessage yanQuMessage = YanQuMessageUtils.buildMessage(Protocol.S_DOU_LUO_DA_LU_BAO_KU_SYNC_RECORD, builder);
        CrossDouLuoDaLuMgr.broadcastActivityServerList(activityId, yanQuMessage);
    }

    /**
     * 获取公告
     */
    public List<DouLuoDaLuTryTrainRecordData> getRecordDataList() {
        int maxCount = config.FIGHT_LOG_LIMIT;
        List<DouLuoDaLuTryTrainRecordData> tmpList = new ArrayList<>(recordList);
        if (tmpList.size() > maxCount) {
            List<DouLuoDaLuTryTrainRecordData> result = new ArrayList<>();
            int size = tmpList.size();
            for (int i = size - 1; i >= size - maxCount ; i--) {
                result.add(tmpList.get(i));
            }
            return tmpList.subList(tmpList.size() - maxCount, tmpList.size());
        } else {
            return tmpList;
        }
    }

    public void removeAreaUser(int regionId, long userId){
        Map<Long, DouLuoDaLuUserData> map = getAreaUserMap().get(regionId);
        if(map != null){
            map.remove(userId);
        }
    }

    public void addAreaUser(int regionId, DouLuoDaLuUserData userData){
        Map<Long, DouLuoDaLuUserData> map = getAreaUserMap().get(regionId);
        if(map != null){
            map.put(userData.getUserId(), userData);
        }else {
            getAreaUserMap().put(regionId, new ConcurrentHashMap<>());
            getAreaUserMap().get(regionId).put(userData.getUserId(), userData);
        }
    }

    /**
     * 抽低价隐藏盲盒
     */
    public boolean drawHideBox() {
        synchronized (box) {
            if (box.getCount() < config.getHideBoxCount()) {
                box.setCount(box.getCount() + 1);
                return true;
            } else {
                return false;
            }
        }
    }

    /**
     * set/get
     */
    public int getActivityId() {
        return activityId;
    }

    public int getGroupId() {
        return groupId;
    }

    public Map<Long, DouLuoDaLuUserData> getAllUserMap() {
        return allUserMap;
    }

    public Map<Long, DouLuoDaLuPatronsBattleData> getBattleDataMap() {
        return battleDataMap;
    }

    public Map<Integer, DouLuoDaLuTeamData> getAllTeamMap() {
        return allTeamMap;
    }

    public Map<Integer, WorldMessageProto.WorldMessageListMsg.Builder> getTeamChatMap() {
        return teamChatMap;
    }

    public WorldMessageProto.WorldMessageListMsg.Builder getTeamChat(int teamId) {
        if(teamChatMap.containsKey(teamId)){
            return teamChatMap.get(teamId);
        }
        synchronized (teamChatMap){
            if(teamChatMap.containsKey(teamId)){
                return teamChatMap.get(teamId);
            }
            teamChatMap.put(teamId, WorldMessageProto.WorldMessageListMsg.newBuilder());
        }
        return teamChatMap.get(teamId);
    }

    public Map<Long, List<DouLuoDaLuTeamData>> getServerTeamMap() {
        return serverTeamMap;
    }

    public List<DouLuoDaLuTeamData> getDeleteList() {
        return deleteList;
    }

    public DouLuoDaLuEventInfo getEventInfo(int eventId) {
        return config.getEventInfo(eventId);
    }

    public Map<Long, List<DouLuoDaLuHelpRecordData>> getHelpRecordDataMap() {
        return helpRecordDataMap;
    }

    public DouLuoDaLuConfig getConfig() {
        return config;
    }

    public Map<Integer, Map<Long, DouLuoDaLuUserData>> getAreaUserMap() {
        return areaUserMap;
    }

    public List<DouLuoDaLuTryTrainRecordData> getRecordList() {
        return recordList;
    }

    public List<DouLuoDaLuEventNoticeData> getEventNoticeDataList() {
        return eventNoticeDataList;
    }

    public List<DouLuoDaLuBattleNoticeData> getBattleNoticeDataList() {
        return battleNoticeDataList;
    }

    public Map<Integer, DouLuoDaLuNpcBloodData> getNpcBlood() {
        return npcBlood;
    }

    public void setNpcBlood(Map<Integer, DouLuoDaLuNpcBloodData> npcBlood) {
        this.npcBlood = npcBlood;
    }

    public static void main(String[] args) {
        CrossDouLouDaLuActivity crossDouLouDaLuActivity = new CrossDouLouDaLuActivity(1, 0);
        DouLuoDaLuConfig tempConfig = new DouLuoDaLuConfig();
        Map<Integer, String> regionMap = new HashMap<>();
        regionMap.put(10001,"10001;8334|10002;1667|30001;1000|40001;3100|50005;79|50006;158|50007;237|60001;300|70001;100|70002;100|70003;100|70004;100" );
        regionMap.put(10002, "10001;6206|10002;1862|10003;931|20001;1100|30001;550|30002;450|40002;3080|50005;86|50006;172|50007;215|60001;250|70001;110|70002;110|70003;110|70004;110");
        regionMap.put(10003,"10002;4102|10003;2051|10004;1230|10005;615|20001;3100|30001;600|30002;400|40003;3060|50004;165|50005;165|50006;263|50007;198|60001;300|70001;120|70002;120|70003;120|70004;120" );
        regionMap.put(10004, "10004;3589|10005;1794|10006;1076|10007;538|20001;5100|30001;650|30002;400|40004;3090|50003;60|50004;120|50005;180|50006;240|50007;270|60001;300|70001;125|70002;125|70003;125|70004;125");
        regionMap.put(10005, "10005;1714|10006;2742|10007;1028|10008;514|20001;7600|30001;700|30002;500|40005;3100|50002;146|50003;182|50004;219|50005;182|50006;109|50007;109|60001;320|70001;130|70002;130|70003;130|70004;130");
        regionMap.put(10006, "10007;2500|10008;1500|10009;750|10010;250|20001;10100|30001;750|30002;500|40006;3100|50001;361|50002;361|50003;181|50004;144|50005;108|50006;72|50007;36|60001;350|70001;140|70002;140|70003;140|70004;140");
        List<DouLuoDaLuRegionInfo> regionInfoList = new ArrayList<>();
        for (Map.Entry<Integer, String> entry : regionMap.entrySet()) {
            DouLuoDaLuRegionInfo douLuoDaLuRegionInfo = new DouLuoDaLuRegionInfo();
            Integer regionId = entry.getKey();
            String eventWeightStr = entry.getValue();
            List<Integer> eventIdList = new ArrayList<>();
            List<Integer> eventWeightList = new ArrayList<>();
            if(!StringUtils.isNullOrEmpty(eventWeightStr)){
                List<String> eventWeightStrList = StringUtils.stringToStringList(eventWeightStr, "\\|");
                for (String eventWeight : eventWeightStrList) {
                    List<Integer> valList = StringUtils.stringToIntegerList(eventWeight, ";");
                    eventIdList.add(valList.get(0));
                    eventWeightList.add(valList.get(1));
                }
            }
            douLuoDaLuRegionInfo.setEventIdList(eventIdList);
            douLuoDaLuRegionInfo.setEventWeightList(eventWeightList);
            douLuoDaLuRegionInfo.setRegionId(regionId);
            regionInfoList.add(douLuoDaLuRegionInfo);
        }
        tempConfig.setRegionInfoList(regionInfoList);

        List<Integer> sevenIdList = new ArrayList<>();
        sevenIdList.add(50001);
        sevenIdList.add(50002);
        sevenIdList.add(50003);
        sevenIdList.add(50004);
        sevenIdList.add(50005);
        sevenIdList.add(50006);
        sevenIdList.add(50007);
        tempConfig.setSevenEventId(sevenIdList);


        List<DouLuoDaLuEventInfo> eventInfoList = new ArrayList<>();
        for (int i = 10001; i <= 10010; i++) {
            DouLuoDaLuEventInfo event = new DouLuoDaLuEventInfo();
            event.setEventId(i);
            event.setEventType(1);
            eventInfoList.add(event);
        }
        for (int i = 20001; i <= 20001; i++) {
            DouLuoDaLuEventInfo event = new DouLuoDaLuEventInfo();
            event.setEventId(i);
            event.setEventType(2);
            eventInfoList.add(event);
        }
        for (int i = 30001; i <= 30002; i++) {
            DouLuoDaLuEventInfo event = new DouLuoDaLuEventInfo();
            event.setEventId(i);
            event.setEventType(3);
            eventInfoList.add(event);
        }
        for (int i = 40001; i <= 40006; i++) {
            DouLuoDaLuEventInfo event = new DouLuoDaLuEventInfo();
            event.setEventId(i);
            event.setEventType(4);
            eventInfoList.add(event);
        }
        for (int i = 50001; i <= 50007; i++) {
            DouLuoDaLuEventInfo event = new DouLuoDaLuEventInfo();
            event.setEventId(i);
            event.setEventType(5);
            eventInfoList.add(event);
        }
        for (int i = 60001; i <= 60001; i++) {
            DouLuoDaLuEventInfo event = new DouLuoDaLuEventInfo();
            event.setEventId(i);
            event.setEventType(6);
            eventInfoList.add(event);
        }
        for (int i = 70001; i <= 70004; i++) {
            DouLuoDaLuEventInfo event = new DouLuoDaLuEventInfo();
            event.setEventId(i);
            event.setEventType(7);
            eventInfoList.add(event);
        }

        tempConfig.setEventInfoList(eventInfoList);
        tempConfig.FOREST_SEVENTEVENT_SECURITY_NUM = "9999999|9999999|9999999|9999999|9999999|9999999";


        Map<Integer, Integer> sevenEventLimitMap = new TreeMap<>();
        String seventeventLimit = "570=950;1140=900;1710=850;2280=800;2850=750;3420=700";
        String[] arr = seventeventLimit.split(";");
        for (String s : arr) {
            String[] split = s.split("=");
            int num = Integer.parseInt(split[0]);
            int param = Integer.parseInt(split[1]);
            sevenEventLimitMap.put(num, param);
        }
        tempConfig.setSevenEventLimitMap(sevenEventLimitMap);
        crossDouLouDaLuActivity.config = tempConfig;

        List<Integer> stoneNumList = new ArrayList<>();

        stoneNumList.add(300);
        stoneNumList.add(700);
        stoneNumList.add(1500);
        stoneNumList.add(2000);
        stoneNumList.add(2500);
        stoneNumList.add(3000);
        stoneNumList.add(3500);
        stoneNumList.add(35000);

        for (Integer stoneNum : stoneNumList) {
            for (int j = 10001; j <= 10006; j++) {
                DouLuoDaLuUserData userData = new DouLuoDaLuUserData();
                userData.setRegionId(j);
                userData.getRegionEventMap().clear();
                int totalTimes = 1000000;
                Map<Integer, Integer> reslutMap = new TreeMap<>();
                for (int i = 0; i < totalTimes; i++) {
                    DouLuoDaLuEventInfo eventInfo = crossDouLouDaLuActivity.randomRegionEventNew(userData, new ArrayList<>(), stoneNum, 0, 0);
                    int regionId = userData.getRegionId();
                    Integer times = userData.getRegionEventMap().getOrDefault(regionId, 0);
                    userData.getRegionEventMap().put(regionId, times + 1);
                    int eventId = eventInfo.getEventId();
                    Integer value = reslutMap.getOrDefault(eventId, 0);
                    reslutMap.put(eventId, value + 1);
                }
                System.out.println( stoneNum + "  "  +  j);
                for (Map.Entry<Integer, Integer> entry : reslutMap.entrySet()) {
                    Integer key = entry.getKey();
                    Integer value = entry.getValue();
                    System.out.println(key + "=" + 1.0*value/totalTimes);
                }
                System.out.println("===========================================");
            }
        }
    }

    public void addLogDouLuoDaLuNpcBloodData(DouLuoDaLuNpcBloodData data){
        CrossAutoLogMgr.add(new LogDouLuoDaLuNpcBloodData(data.getActivityId(), data.getEventId(), data.getBlood(), data.getUpdateTime(), data.getUserNum(),
                data.getBaseValue1(), data.getStartRank1(), data.getEndRank1(), data.getNum1(),
                data.getEarnSum1(), data.getBaseValue2(), data.getStartRank2(), data.getEndRank2(), data.getNum2(), data.getEarnSum2(), data.getBaseValue3(), data.getBaseValue4()));
    }

    public ActivityInfo getActivityInfo() {
        return activityInfo;
    }

    public void setActivityInfo(ActivityInfo activityInfo) {
        this.activityInfo = activityInfo;
    }

    public int adminChangeTeamName(int teamId, String teamName){
        DouLuoDaLuTeamData teamData = getAllTeamMap().get(teamId);
        if(null == teamData){
            return GameErrorCode.E_DOU_LUO_DA_LU_TEAM_NO_EXIST;
        }
        teamData.setName(teamName);
        changeTeamRank(teamData);
        return 0;
    }

    public JSONObject adminQueryTeamData(long userId){
        JSONObject dataObj = new JSONObject();
        DouLuoDaLuUserData userData = allUserMap.get(userId);
        if(null != userData){
            int teamId = userData.getTeamId();
            String teamName = "";
            DouLuoDaLuTeamData teamData = allTeamMap.get(teamId);
            if(null != teamData){
                teamName = teamData.getName();
            }
            dataObj.put("teamId", teamId);
            dataObj.put("teamName", teamName);
        }
        return dataObj;
    }
}
